I don't have any experience with language design but I will give an answer anyway.
Your end goal is important here. Since you want to learn to create a programming language, don't expect an amazing revolutionary programming language. You will need to solve some problem to do that.
So lets suppose we are building a simple object oriented programming language like python or php.
First thing you should do is define all the syntax. You can easily do that by writing them in a notebook. Make the statements, operators, blocks, functions, objects, classes etc.
Now lets make the interpreter. Compiled languages are often complex as they involve assembling a binary or executables for specific machine. So stick to the interpreter. Your interpreter should do the following
2 + 3;
add(2, 3); // inside the interpreter's code
add() function in your interpreter is in the core responsible for addition operation.
Most of the time, you will be dealing with basic operations on integers, floats and characters. null, void and infinity can be seen as integer inside your interpreter. Control statements and loops can also be changed into operations. if...else statements can be executed as following:
if (some_condition) {
some statements;
}
// The above can be solved as:
function if_statement(some_condition, block to solve) {
if ( solve_condition(some_condition) ) {
solve_block(block to solve);
}
}
It is just a hint of what you can do with if...else statement. Simply parse it as an if...else statement inside your interpreter. You can do the same with loops.
Lets talk about objects and classes now. Classes in itself are blocks. A block that contains functions and variables that are associated with some object. Problem is that class in itself is just a blueprint. Main concern is with objects. So instead of parsing a class, put it aside for later. As the interpreter encounters an object instantiation statement, it should parse the class at that instant. If you know the OO paradigm, you know that constructor is the first method called on object instantiation. Each object contains a reference within this. There are some magical methods that allow overloading behaviours of object on operations. You just need to parse them seperately as blocks. Then statements and after that operations. At the very core, you will find that there are limited basic operations that makes the complex operations possible.
Another thing you will need to consider are namespaces and scope. Simply implement an array containing the names of variables visible in the scope.
In the end, provide a standard library full of functions and methods for os api, networking, date and time... as many as you can.
Instead of looking for someone else opinion, you should start writing code first, find the right way later.